package pl.skubicha.service;

import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.jboss.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import pl.skubicha.domain.Subjects;
import pl.skubicha.exceptions.EntityConstraintException;
import pl.skubicha.exceptions.SubjectNotFoundException;
import pl.skubicha.repository.SubjectRepository;
import pl.skubicha.response.SubjectDTO;
import pl.skubicha.utils.SubjectMapper;

@Service
public class SubjectsRepositoryService implements SubjectService {

	private static Logger logger = Logger.getLogger( SubjectsRepositoryService.class );

	@Autowired
	private SubjectRepository subjectRepository;

	@Transactional( readOnly = true )
	@Override
	public Page< Subjects > findAll( final Pageable page ) {
		return subjectRepository.findAll( page ); 
	}

	@Transactional( readOnly = true )
	@Override
	public Page< Subjects > findAllMatching( final String searchString, final Pageable page ) {
		logger.debug( "Wyszukuję przedmiot o nazwie %" + searchString + "%" );
		return subjectRepository.findAllMatching( "%" + searchString + "%", page ); 
	}

	@Override
	public List< Subjects > findAllSubjectsForGroup( final Integer id ) {
		logger.debug( "Wyszukuję przedmioty dla grupy o id " + id );
		return subjectRepository.findAllSubjectsForGroup( id );
	}

	@Transactional( readOnly = true )
	@Override
	public Subjects findById( final Integer id ) throws SubjectNotFoundException {
		logger.debug( "Wyszukuję przedmiot o id: " + id );
		final Subjects subject = subjectRepository.findOne( id );

		if ( subject == null ) {
			logger.debug( "Nie znaleziono przedmiotu o id: " + id );
			throw new SubjectNotFoundException();
		}

		return subject;
	}

	@Transactional
	@Override
	public Subjects create( final SubjectDTO toCreate ) {
		logger.debug( "Tworzę nowy przedmiot: " + toCreate );
		final Subjects subject = SubjectMapper.map( toCreate );
		return subjectRepository.save( subject );
	}

	@Transactional( rollbackFor = SubjectNotFoundException.class )
	@Override
	public Subjects update( final SubjectDTO updated ) throws SubjectNotFoundException {

		logger.debug( "Aktualizuję przedmiot: " + updated );

		final Subjects subject = subjectRepository.findOne( updated.getId() );

		if ( subject == null ) {
			logger.debug( "Nie znaleziono przedmiotu o id: " + updated.getId() ); 
			throw new SubjectNotFoundException();
		}

		subject.update( updated.getUser(), updated.getSubjectName(), updated.getGroups() );

		return subject;
	}

	@Transactional( rollbackFor = {SubjectNotFoundException.class, EntityConstraintException.class} )
	@Override
	public Subjects delete( final Integer personId ) throws SubjectNotFoundException, EntityConstraintException {

		logger.debug( " Usuwam przedmiot o id: " + personId );

		final Subjects deleted = subjectRepository.findOne( personId );

		if ( deleted == null ) {
			logger.debug( "Nie znaleziono przedmiotu o id: " + personId );
			throw new SubjectNotFoundException( "Nie znaleziono przedmiotu" );
		}
		
		if(CollectionUtils.isNotEmpty( deleted.getGroups() )){
			throw new EntityConstraintException( "Przedmiot " + deleted.getSubjectName() + " posiada referencje do grup!" );
		}

		subjectRepository.delete( deleted );
		return deleted;
	}

	public void setSubjectRepository( final SubjectRepository subjectRepository ) {
		this.subjectRepository = subjectRepository;
	}
}
